package com.easyexcel.usr.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.easyexcel.usr.bean.Person;
import com.easyexcel.usr.service.ReadService;
import com.easyexcel.usr.util.WriteForeadUtils;
import com.easyexcel.usr.validate.HibernateValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Package: com.test.excel
 * @ClassName: ExcelListener
 * @Author: shuaijun Wang
 * @CreateTime: 2020/10/13 15:28
 * @Description:
 */
@Slf4j
public class SimpleReadListener extends AnalysisEventListener<Person> {

    List<Person> saveList = new ArrayList<>();

    List<String> validatePersonList = new ArrayList<>();

    private final HttpServletResponse response;
    private final ReadService readService;

    /**
     * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    public SimpleReadListener(HttpServletResponse response,ReadService readService) {
        // 这里是demo，所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        this.response = response;
        this.readService = readService;
    }


    @Override
    public void invoke(Person person, AnalysisContext analysisContext) {
       validateParamsEmpty(person,analysisContext);

    }

    /**
     * 校验数据是否为空的情况
     * @param person Excel读取对象
     * @param analysisContext 参数对象
     */
    private void validateParamsEmpty(Person person,AnalysisContext analysisContext){
        Validator validator = HibernateValidator.getValidator();
        Set<ConstraintViolation<Person>> validateSet = validator.validate(person, Default.class);
        if (validateSet != null && !validateSet.isEmpty()) {
            for (ConstraintViolation<Person> next : validateSet) {
                final String message = next.getMessage();
                if(!StringUtils.isEmpty(message)){
                    log.error("数据存在问题。。。。。。。。。");
                    validatePersonList.add(MessageFormat.format("第【{0}】行数据存在问题：【{1}】",analysisContext.readRowHolder().getRowIndex(),message));
                }
            }
        }else{
            saveList.add(person);
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据，确保最后遗留的数据也存储到数据库
        if(!validatePersonList.isEmpty()){
            log.info("数据存在问题");
            WriteForeadUtils.getResultObject(response, validatePersonList.get(0));
        }else{
            final List<Person> people = validatePersonIdCard();
            StringBuilder stringBuilder = new StringBuilder();
            if(!people.isEmpty()){
                for(Person person : people){
                    final String name = person.getName();
                    stringBuilder.append(name).append("和");
                }
                stringBuilder.append("的身份证重复，重复的身份证为：【").append(people.get(0).getIdCard()).append("】");
                final String string = stringBuilder.toString();
                log.info("数据存在问题:身份证号有重复的。。。");
                WriteForeadUtils.getResultObject(response, string);
            }else{
                readService.readSimpleExcel(saveList);
            }
        }
    }


    /**
     * 校验不同的人身份证是否重复
     */
    private List<Person> validatePersonIdCard(){
        final Map<String, List<Person>> listMap = saveList
                .stream()
                .collect(Collectors.groupingBy(Person::getIdCard));
        List<Person> p =new ArrayList<>();
        listMap.forEach((idcardGroup,person)->{
            final int size = person.size();
            if(size>1){
                saveList.forEach(excelPerson -> {
                    final String idCard = excelPerson.getIdCard();
                    if(idcardGroup.equals(idCard)){
                        p.add(excelPerson);
                    }
                });
            }
        });
        return p;
    }













}
